﻿using Dto;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using StackExchange.Redis;

namespace Dlpad.Services
{
    public class DictCacheInitializerHostedService : IHostedService
    {
        private readonly IServiceProvider _serviceProvider;
        private readonly ILogger<DictCacheInitializerHostedService> _logger;

        public DictCacheInitializerHostedService(IServiceProvider serviceProvider, ILogger<DictCacheInitializerHostedService> logger)
        {
            _serviceProvider = serviceProvider;
            _logger = logger;
        }

        public async Task StartAsync(CancellationToken cancellationToken)
        {
            _logger.LogInformation("DictCacheInitializerHostedService 启动...");

            try
            {
                using var scope = _serviceProvider.CreateScope();//创建子依赖注入容器

                //创建子作用域
                var dictTypeService = scope.ServiceProvider.GetRequiredService<IDictTypeService>(); //负责加载字典类型（如 sys_user_sex, sys_show_hide）
                var dictDataService = scope.ServiceProvider.GetRequiredService<IDictDataService>(); //负责加载字典数据（如 男、女、未知）
                var cacheService = scope.ServiceProvider.GetRequiredService<ICacheService>(); //负责清理和运维缓存

                _logger.LogInformation("开始初始化字典缓存...");

                //获取Redis连接
                var redis = scope.ServiceProvider.GetRequiredService<IConnectionMultiplexer>();
                var db = redis.GetDatabase();

                // 1. 清除所有现有字典缓存
                _logger.LogInformation("正在清除现有字典缓存...");
                // 暴力清理所有相关键
                var server = redis.GetServer(redis.GetEndPoints().First());
                var keys = server.Keys(pattern: "Dlpad_dict_*").ToArray();
                if (keys.Length > 0)
                {
                    await db.KeyDeleteAsync(keys);
                    _logger.LogInformation($"已清理 {keys.Length} 个缓存键");
                }

                _logger.LogInformation("开始重新加载字典缓存...");
                await cacheService.ClearAllDictCacheAsync();
                _logger.LogInformation("字典缓存清除完成");

                // 2. 加载所有字典类型到缓存（新增这部分）
                _logger.LogInformation("正在加载字典类型数据到缓存...");

                var dictTypes = await dictTypeService.GetAllDictTypesAsync(); // 这会自动缓存 加载类型缓存

                _logger.LogInformation($"成功加载 {dictTypes.Count} 个字典类型到缓存");

                // 3. 为每个字典类型预加载字典数据到缓存
                _logger.LogInformation("正在预加载字典数据...");
                int totalDictDataCount = 0;
                int successCount = 0;
                int failCount = 0;

                foreach (var dictType in dictTypes)
                {
                    try
                    {
                        var dictData = await dictDataService.GetDictDataByTypeAsync(dictType.DictType);//加载数据缓存

                        totalDictDataCount += dictData.Count;
                        successCount++;
                        _logger.LogInformation($"字典类型 {dictType.DictType} 加载了 {dictData.Count} 条数据");
                    }
                    catch (Exception ex)
                    {
                        failCount++;
                        _logger.LogWarning($"加载字典类型 {dictType.DictType} 的数据时出错: {ex.Message}");
                    }
                }

                // 4. 加载所有字典数据的完整列表到缓存（用于分页查询）
                _logger.LogInformation("正在加载字典数据完整列表...");
                await LoadAllDictDataToCache(dictDataService);

                _logger.LogInformation($"字典缓存初始化完成，共加载 {dictTypes.Count} 个字典类型，{totalDictDataCount} 条字典数据");
                _logger.LogInformation($"成功: {successCount} 个类型，失败: {failCount} 个类型");
                _logger.LogInformation("DictCacheInitializerHostedService 完成");
            }
            catch (Exception ex)
            {
                _logger.LogError($"DictCacheInitializerHostedService 执行失败: {ex.Message}");
                // 不抛出异常，避免应用启动失败
            }
        }

        /// <summary>
        /// 加载所有字典数据的完整列表到缓存
        /// </summary>
        private async Task LoadAllDictDataToCache(IDictDataService dictDataService)
        {
            try
            {
                // 加载所有字典数据（第一页，用于初始化缓存）
                var query = new DictDataQueryDto
                {
                    PageNumber = 1,
                    PageSize = 100 // 加载前100条，避免数据量过大
                };

                var result = await dictDataService.GetDictDataListAsync(query);
                _logger.LogInformation($"字典数据列表缓存初始化完成，共 {result.TotalCount} 条数据");
            }
            catch (Exception ex)
            {
                _logger.LogWarning($"加载字典数据列表缓存时出错: {ex.Message}");
            }
        }

        public Task StopAsync(CancellationToken cancellationToken)
        {
            return Task.CompletedTask;
        }
    }
}